package com.software.client
//
//import org.apache.log4j.{Level, Logger}
//import org.apache.spark.ml.regression.{GBTRegressor, LinearRegression, LinearRegressionModel, RandomForestRegressor}
//import org.apache.spark.SparkConf
//import org.apache.spark.ml.{Pipeline, PipelineModel}
//import org.apache.spark.ml.evaluation.RegressionEvaluator
//import org.apache.spark.ml.classification.RandomForestClassifier
//import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}
//import org.apache.spark.ml.feature.{OneHotEncoder, StringIndexer}
//import org.apache.spark.sql.functions.expr
//import org.apache.spark.ml.feature.VectorAssembler
//
///**
// * 机器学习
// */
object MachinePriceExample {
//
//  Logger.getLogger("org").setLevel(Level.ERROR)
//
//  def main(args: Array[String]): Unit = {
//
//    //1.创建Spark环境配置对象
//    val conf = new SparkConf().setAppName("MachineFlightFare").setMaster("local")
//
//    //2.创建SparkSession对象
//    val spark: SparkSession = SparkSession.builder().config(conf)
//      .config("spark.sql.legacy.timeParserPolicy", "LEGACY")
//      .getOrCreate()
//
//    var data = spark.read.option("delimiter", ",")
//      .option("header", true)
//      .option("multiLine", true)
//      .csv("input\\source.csv")
//
//    import spark.implicits._
//    import org.apache.spark.sql.functions._
//
//    //1.数据处理 正则表达式的替换
//    data = regexpReplace(data, "date", "/", "-")
//    //    data.show(5)
//
//    val newDateColumn = to_date(col("Date_of_Journey"), "dd-MM-yyyy")
//    //正序
//    val newDateFormat = date_format(newDateColumn, "yyyy-MM-dd")
//    val updatedData = data.withColumn("Date_of_Journey", newDateFormat)
//    //    updatedData.show(20)
//
//    //2.数据清洗 删除不是空值的记录
//    val filteredData = updatedData.filter(col("Date_of_Journey").isNotNull
//      && col("Duration").isNotNull
//      && col("Price").isNotNull
//      && col("Airline").isNotNull)
//
//
//
//    //3.数据加工
//    //3.1 数据格式转换
//    filteredData.withColumn("Date_of_Journey", (to_date(col("Date_of_Journey"), "yyyy-MM-dd")))
//
//    //    filteredData.show(10)
//
//    //3.2 日期按年、月拆分进行转换
//    val featureData = filteredData.withColumn("year", year($"Date_of_Journey"))
//      .withColumn("month", month($"Date_of_Journey"))
//      .withColumn("day", dayofmonth($"Date_of_Journey"))
//      .select("year", "month", "day","Airline","Duration", "Price")
//
////            featureData.show(10)
//
//    //3.2 自然语言使用StringIndexer进行标签编码
//    val indexer1 = new StringIndexer()
//      .setInputCol("Duration")
//      .setOutputCol("DurationIndex")
//
//    val indexer2 = new StringIndexer()
//      .setInputCol("Airline")
//      .setOutputCol("AirlineIndex")
//
////    val indexer3 = new StringIndexer()
////      .setInputCol("Arrival_Time")
////      .setOutputCol("Arrival_TimeIndex")
//
//    //3.3 拟合StringIndexer模型，生成编码器
//    //这个代码的目的是将 featureData DataFrame 中的 Airline 列进行标签编码，
//    // 并生成编码后的 DataFrame datamodel。
//    // 这个编码后的 DataFrame 可以用于后续的特征工程和机器学习模型训练。
//
//    val pipeline = new Pipeline().setStages(Array(indexer1, indexer2))
//    val pipelineModel: PipelineModel = pipeline.fit(featureData)
//    val datamodel = pipelineModel.transform(featureData)
//
////            datamodel.show(20)
//
//    //3.4 生成新的数据集DataFrame
//    //datamodel.map() 函数将 datamodel DataFrame 中的每一行数据转换成一个元组，包含了年份、月份、编码后的国家标签、平均温度四个字段。
//    val result = datamodel.select(
//      col("year"),
//      col("month"),
//      col("day"),
//      col("AirlineIndex"),
//      col("DurationIndex"),
//      col("Price").cast("double")
//    ).toDF("year", "month", "day","AirlineIndex", "DurationIndex", "Price")
//
////            result.show(10)
//
//    //3.5 数据预处理
//    // 创建了一个 VectorAssembler 对象，并设置了输入列和输出列。setInputCols 方法接收一个字符串数组，
//    // 参数是要组合成向量的列名，这里是 "year"、"month" 和 "countryIndex"。
//    // setOutputCol 设置了输出列的名称为 "features"，该列将包含组合后的向量特征。
//    val assembler = new VectorAssembler()
//      .setInputCols(Array("year", "month","day","DurationIndex","AirlineIndex")) // 填写实际的日期特征列名
//      .setOutputCol("features")
//
//    //使用 transform 方法将 result中的列数组转换为向量列。transform方法接收一个输入DataFrame，
//    //并根据之前设置的输入和输出列进行转换。转换后的结果保存在新的 DataFrame中，这里命名为assembledData。
//    //然后，使用select方法选择了转换后的features列和原始的temperature列，生成最终的 DataFrame。
//    val assembledData = assembler.transform(result).select("Price", "features")
//
//    //    assembledData.printSchema()
////        assembledData.show(20)
//
//    //4.1拆分数据集为 训练集 和 测试集（按比例拆分） dataframe
//    val Array(trainingData, testData) = assembledData.randomSplit(Array(0.8, 0.2))
//    //
//    //    trainingData.show(10)
//    //    testData.show(10)
//
///*============================================================*/
////    4.2 模型一： 线性回归模型
//        //调用 setLabelCol 函数设置目标变量列为 temperature，
//        //调用 setFeaturesCol 函数设置特征列为 features。
//        //这些设置意味着，LinearRegression 将会使用 temperature 列作为目标变量，
//        //使用 features 列作为特征变量来训练和预测线性回归模型。
///*        val lr = new LinearRegression()
//          //使用 temperature 列作为目标变量，
//          .setLabelCol("Price")
//          // 使用 features 列作为特征变量来训练和预测线性回归模型。
//          .setFeaturesCol("features")
//
//        //模型训练
//        val model = lr.fit(trainingData)*/
///*=============================================================*/
//
//
///*============================================================*/
///*    //模型二： 随机森林模型
//    val rf = new  RandomForestRegressor()
//      .setLabelCol("Price")
//      .setFeaturesCol("features")
//      .setNumTrees(20)
//      .setMaxDepth(10)
//      .setMaxBins(400)
//
//    //模型训练
//    val model = rf.fit(trainingData)*/
//
///*============================================================*/
//
//
///*============================================================*/
//
//    //模型三： 梯度提升回归模型
//    val gbt = new GBTRegressor()
//      .setLabelCol("Price")
//      .setFeaturesCol("features")
//      .setMaxIter(20) // 最大迭代次数 20
//      .setMaxDepth(10) // 最大深度 10
//      .setStepSize(0.2) // 步长 0.1
//      .setMaxBins(400)
//
//    //模型训练
//    val model = gbt.fit(trainingData)
//
//    // 测试集进行预测
//    val predictions = model.transform(testData)
//
//
//    // 打印预测结果
//    predictions.select("features", "Price", "prediction").show(00)
//
///*============================================================*/
//
//
//    //均方误差
//   val evaluator = new RegressionEvaluator()
//      .setLabelCol("Price")
//      .setPredictionCol("prediction")
//      .setMetricName("mse")
//    val mse = evaluator.evaluate(predictions)
//
//    println(s"MSE = $mse")
//
//
//    // 关闭SparkSession
//    spark.stop()
//  }
//
//  //正则替换
//  def regexpReplace(df: DataFrame, columnName: String, regexp: String, newValue: Any): DataFrame = {
//    val exprString: String = "regexp_replace(" + columnName + ",'" + regexp + "','" + newValue + "')"
//    df.withColumn(columnName, expr(exprString).alias(columnName))
//  }
//
}